﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Animation;
using GameApplication.Helper;
using GameApplication.MiniGame;
using Logic;
using Logic.Locations;
using Logic.Units;

namespace GameApplication
{
    //<summary>
    //Логика взаимодействия для Demo.xaml
    //</summary>
    public partial class Demo : Page
    {
        private readonly ManagerGames _manager;
        private int _sectorId = -1;

        public Demo()
        {
            InitializeComponent();

            #region Initialize

            Location location = new Location();

            location.AddSector(new Sector(0)
            {
                Adjacent = new List<int> {1, 3, 4},
                Defenders = new List<IUnit>
                {
                    new Infantry(count: 2)
                }
            });

            location.AddSector(new Sector(1)
            {
                Adjacent = new List<int> {0, 4, 5, 2},
                Defenders = new List<IUnit>
                {
                    new Infantry(UserState.Enemy)
                }
            });

            location.AddSector(new Sector(2)
            {
                Adjacent = new List<int> {1, 5},
                Defenders = new List<IUnit>
                {
                    new Infantry(UserState.Enemy),
                    new Tank(UserState.Enemy)
                }
            });

            location.AddSector(new Sector(3)
            {
                Adjacent = new List<int> {0, 4, 6},
                Defenders = new List<IUnit>
                {
                    new Infantry(UserState.Enemy),
                    new ArmoredCar(UserState.Enemy),
                }
            });

            location.AddSector(new Sector(4)
            {
                Adjacent = new List<int> {0, 1, 3, 5, 6, 7},
                Defenders = new List<IUnit>
                {
                    new Infantry(UserState.Enemy),
                    new ArmoredCar(UserState.Enemy),
                }
            });

            location.AddSector(new Sector(5)
            {
                Adjacent = new List<int> {1, 2, 4, 7, 8},
                Defenders = new List<IUnit>
                {
                    new Infantry(UserState.Enemy),
                    new ArmoredCar(UserState.Enemy),
                }
            });

            location.AddSector(new Sector(6)
            {
                Adjacent = new List<int> {3, 4, 7},
                Defenders = new List<IUnit>
                {
                    new Infantry(UserState.Enemy),
                    new ArmoredCar(UserState.Enemy),
                }
            });

            location.AddSector(new Sector(7)
            {
                Adjacent = new List<int> {4, 5, 6, 8},
                Defenders = new List<IUnit>
                {
                    new Infantry(UserState.Enemy),
                    new ArmoredCar(UserState.Enemy),
                }
            });

            location.AddSector(new Sector(8)
            {
                Adjacent = new List<int> {5, 7},
                Defenders = new List<IUnit>
                {
                    new Infantry(UserState.Enemy),
                    new ArmoredCar(UserState.Enemy),
                }
            });

            #endregion

            _manager = new ManagerGames(location);

            _manager.ChangeStep += OnChangeStep;

            _manager.GameOver += () => MessageBox.Show("GameOver");

            _manager.Start();

            UpdateAllUi();

            SetEvents();

            _manager.ChangeStep += step => SrtTitle(step.ToString());

            _manager.Reset += () => { _sectorId = -1; };

            _manager.ElementChanged += OnElementChanged;
        }

        private void OnElementChanged(int i)
        {
            UpdateUiElement(i,
                MyGrid.Children.Cast<FrameworkElement>()
                    .Where(x => x.GetType() == typeof (Button))
                    .FirstOrDefault(x => Convert.ToInt32(x.Tag) == i) as Button);
        }

        private void SetEvents()
        {
            foreach (Button item in MyGrid.Children.Cast<FrameworkElement>()
                .Where(x => x.GetType() == typeof (Button)).Cast<Button>())
            {
                item.Click += (sender, args) =>
                {
                    Button items = sender as Button;
                    if (items == null) return;

                    int id = Convert.ToInt32(items.Tag);

                    switch (_manager.Step)
                    {
                        case Step.Distribution:
                            //TODO Удалить когда будет механизм выбора войск для перемещения
                            _manager.UnitToMove.AddReinforcement(_manager.SectorNewTroops);

                            _manager.Distribution(id);
                            break;
                        case Step.Engagement:
                        case Step.Moving:

                            if (_sectorId == -1)
                            {
                                _manager.UnitToMove.Clear();
                                if (_manager.Location[id].State != SectorState.Player ||
                                    _manager.Location[id].Count == 1)
                                    return;
                                _sectorId = id;

                                ListBoxPlayer.ItemsSource = null;
                                ListBoxPlayer.ItemsSource = _manager.Location[id].ToWpf();
                                ListBoxMove.ItemsSource = _manager.UnitToMove.ToWpf();

                                ThicknessAnimation animation = new ThicknessAnimation
                                {
                                    To = new Thickness(0, 0, 0, 0),
                                    Duration = new Duration(TimeSpan.FromSeconds(0.5))
                                };
                                PlayerUnits.BeginAnimation(MarginProperty, animation);
                            }
                            else
                            {
                                if (_sectorId != id && _sectorId != -1)
                                {
                                    if (_manager.Step == Step.Engagement)
                                    {
                                        _manager.SetMiniGame(new PageGame());
                                        _manager.Engagement(_sectorId, id);
                                    }
                                    else
                                    {
                                        _manager.Moving(_sectorId, id);
                                    }
                                    _manager.UnitToMove.Clear();
                                    _sectorId = -1;
                                }
                                else
                                {
                                    _manager.UnitToMove.Clear();
                                    _sectorId = -1;
                                }


                                ThicknessAnimation animation = new ThicknessAnimation
                                {
                                    To = new Thickness(-240, 0, 0, 0),
                                    Duration = new Duration(TimeSpan.FromSeconds(0.5))
                                };
                                PlayerUnits.BeginAnimation(MarginProperty, animation);
                            }
                            break;
                    }
                };
            }
        }

        private void OnChangeStep(Step step)
        {
            if (step == Step.Distribution)
            {
                ListBoxDistribution.ItemsSource = null;
                ListBoxDistribution.ItemsSource = _manager.SectorNewTroops.ToWpf();

                ThicknessAnimation animation = new ThicknessAnimation
                {
                    To = new Thickness(0, 0, 0, 0),
                    Duration = new Duration(TimeSpan.FromSeconds(0.5))
                };
                GridDistribution.BeginAnimation(MarginProperty, animation);
            }
            else
            {
                ThicknessAnimation animation = new ThicknessAnimation
                {
                    To = new Thickness(0, 0, 0, -150),
                    Duration = new Duration(TimeSpan.FromSeconds(0.5))
                };
                GridDistribution.BeginAnimation(MarginProperty, animation);
            }
        }

        private static void SrtTitle(string step)
        {
            Window cmd = Application.Current.Properties["MyMainWindow"] as Window;
            if (cmd == null) return;
            cmd.Title = step;
        }

        private void UpdateAllUi()
        {
            foreach (Button item in MyGrid.Children.Cast<FrameworkElement>()
                .Where(x => x.GetType() == typeof (Button)).Cast<Button>())
            {
                int id = Convert.ToInt32(item.Tag);
                UpdateUiElement(id, item);
            }
        }

        private void UpdateUiElement(int id, Button item)
        {
            if (item == null) return;
            Sector sector = _manager.Location[id];

            item.Style =
                (Style) (sector.State == SectorState.Player ? FindResource("StylePlayer") : FindResource("StyleEnemy"));
            item.Content = sector.Count;
            item.FontSize = 30;
        }

        private void ListBoxPlayer_OnSelected(object sender, RoutedEventArgs e)
        {
            IEnumerable<UnitWpf> sectorFrom = ListBoxPlayer.ItemsSource as IEnumerable<UnitWpf>;
            int select = ListBoxPlayer.SelectedIndex;
            if (sectorFrom == null || select < 0) return;

            List<UnitWpf> wp = sectorFrom as List<UnitWpf> ?? sectorFrom.ToList();
            List<IUnit> units = wp.Select(wpf => wpf.Unit).ToList();
            if (wp.Sum(x => x.LocalCount) == 1)
            {
                return;
            }
            IUnit unit = GetOneUnit(units.ToArray()[select]);

            _manager.UnitToMove.AddReinforcement(unit);

            foreach (UnitWpf item in wp.Where(item => item.Unit.GetType() == unit.GetType()))
            {
                item.LocalCount--;
                break;
            }
            ListBoxMove.ItemsSource = _manager.UnitToMove.ToWpf();
        }

        private void ListBoxMove_OnMouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
            IEnumerable<UnitWpf> sectorFrom = ListBoxPlayer.ItemsSource as IEnumerable<UnitWpf>;
            int select = ListBoxMove.SelectedIndex;
            if (sectorFrom == null || select < 0) return;

            IUnit unit = GetOneUnit(_manager.UnitToMove.ToArray()[select]);
            _manager.UnitToMove.RemoveReinforcement(unit);

            foreach (UnitWpf item in sectorFrom.Where(item => item.Unit.GetType() == unit.GetType()))
            {
                item.LocalCount++;
                break;
            }
            ListBoxMove.ItemsSource = _manager.UnitToMove.ToWpf();
        }

        /// <summary>
        ///     Плучить юнита заданного типа
        /// </summary>
        /// <param name="unit">Отряд какого типа нужен юнит</param>
        /// <returns>Юнит заданного типа</returns>
        private IUnit GetOneUnit(IUnit unit)
        {
            switch (unit.GetType().Name)
            {
                case "Infantry":
                    return new Infantry();
                case "ArmoredCar":
                    return new ArmoredCar();
                case "Tank":
                    return new Tank();
            }
            throw new NotImplementedException("Неизвесные войска!");
        }
    }
}